﻿using Emgu.CV.Structure;
using Emgu.CV;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV.CvEnum;

namespace OpenCvApplication.View.CommonView
{
    public partial class FrmGrabCut : Form
    {
        private Point RectStartPoint;
        private Rectangle Rect = new Rectangle();
        private bool drag = false;
        private bool resizing = false;
        private const int BorderWidth = 10; // 可调整大小的边框宽度
        private Brush selectionBrush = new SolidBrush(Color.FromArgb(128, 72, 145, 220));
        public FrmGrabCut()
        {
            InitializeComponent();


        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            // 确定是否在矩形框内点击
            if (Rect.Contains(e.Location))
            {
                if (IsOnBorder(e.Location))
                {
                    RectStartPoint = e.Location;
                    resizing = true;
                }
                else
                {
                    drag = true;
                    RectStartPoint = e.Location;
                }
            }
            else
            {
                RectStartPoint = e.Location;
                Rect = new Rectangle();
            }
            Invalidate();
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (drag)
            {
                // 如果正在拖动，更新矩形框的位置
                Rect.Location = new Point(Rect.Left + (e.X - RectStartPoint.X),
                                          Rect.Top + (e.Y - RectStartPoint.Y));
                RectStartPoint = e.Location;
            }
            else if (resizing)
            {
                // 如果正在调整大小，更新矩形框的大小
                Rect.Size = new Size(Rect.Width + (e.X - RectStartPoint.X),
                                     Rect.Height + (e.Y - RectStartPoint.Y));
                RectStartPoint = e.Location;
            }
            else if (e.Button == MouseButtons.Left)
            {
                // 否则，更新矩形框的大小
                Point tempEndPoint = e.Location;
                Rect.Location = new Point(
                    Math.Min(RectStartPoint.X, tempEndPoint.X),
                    Math.Min(RectStartPoint.Y, tempEndPoint.Y));
                Rect.Size = new Size(
                    Math.Abs(RectStartPoint.X - tempEndPoint.X),
                    Math.Abs(RectStartPoint.Y - tempEndPoint.Y));
            }
            pictureBox1.Invalidate();
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            drag = false;
            resizing = false;
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {

            // 使用半透明颜色
            if (pictureBox1.Image != null)
            {
                if (Rect != null && Rect.Width > 0 && Rect.Height > 0)
                {
                    e.Graphics.FillRectangle(selectionBrush, Rect);
                }
            }
        }
        private bool IsOnBorder(Point point)
        {
            var borders = new Rectangle[] {
            new Rectangle(Rect.Left, Rect.Top, Rect.Width, BorderWidth),
            new Rectangle(Rect.Left, Rect.Bottom - BorderWidth, Rect.Width, BorderWidth),
            new Rectangle(Rect.Left, Rect.Top, BorderWidth, Rect.Height),
            new Rectangle(Rect.Right - BorderWidth, Rect.Top, BorderWidth, Rect.Height)
        };

            foreach (var border in borders)
            {
                if (border.Contains(point))
                    return true;
            }

            return false;
        }
        private void FrmGrabCut_Load(object sender, EventArgs e)
        {

        }

        private void FrmGrabCut_FormClosing(object sender, FormClosingEventArgs e)
        {
            img?.Dispose();
            selectionBrush.Dispose();
            this.Dispose();
        }

        public string ImageExtension { get; private set; }
        public string[] ImageExtensions { get; } = { ".bmp", ".jpg", ".jpeg", ".png" };
        string path;
        Image<Bgra, byte> img;
        /// <summary>
        /// 选择图像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            using OpenFileDialog openFileDialog = new OpenFileDialog();
            if (string.IsNullOrEmpty(ImageExtension))
            {
                string temp = String.Join(";", ImageExtensions.Select(t => $"*{t}"));
                ImageExtension = $"Image Files ({temp})|{temp}";
            }
            openFileDialog.Filter = ImageExtension;
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                string selectedFile = openFileDialog.FileName;
                path = selectedFile;
                this.pictureBox1.Image?.Dispose();
                this.pictureBox1.Image = new Bitmap(path);
                img?.Dispose();
                img = new Image<Bgra, byte>(path);

            }
        }
        /// <summary>
        /// 生成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            float scaleX = (float)img.Width / pictureBox1.Width;
            float scaleY = (float)img.Height / pictureBox1.Height;

            Rectangle rect = new Rectangle(
                (int)(Rect.Left * scaleX),
                (int)(Rect.Top * scaleY),
                (int)(Rect.Width * scaleX),
                (int)(Rect.Height * scaleY));

            rect.Intersect(new Rectangle(0, 0, img.Width, img.Height));
            // 加载图像
            Image<Bgr, byte> image = img.Convert<Bgr, byte>();

            // 创建掩码
            Image<Gray, byte> mask = new Image<Gray, byte>(image.Width, image.Height, new Gray(0));

            // 创建矩形来指定前景区域（文字区域）

            // 创建背景模型和前景模型
            Mat bgdModel = new Mat();
            Mat fgdModel = new Mat();

            // 运行GrabCut算法
            CvInvoke.GrabCut(image, mask, rect, bgdModel, fgdModel, 5, GrabcutInitType.InitWithRect);

            // 将掩码中的可能前景和确定前景区域设为白色，其他区域设为黑色
            CvInvoke.Threshold(mask, mask, 2, 255, ThresholdType.Binary);

            // 提取前景（文字）
            Image<Bgr, byte> foreground = image.Copy(mask);

            pictureBox2.Image?.Dispose();
            pictureBox2.Image = foreground.Bitmap;
        }
    }
}
